# 简单示例，演示如何使用简单的 2D 卷积函数进行图像处理
# 代码说明：
# 输入图像：
# 一个 6x6 的矩阵，左上角和右下角是亮区（值为1），其他是暗区（值为0）
#
# 卷积核：
# 3x3 边缘检测核，中心是8，周围是-1
# 这种核会突出显示图像中亮度变化大的区域（边缘）
#
# 卷积操作：
# stride=1：每次滑动1个像素
# padding=1：在图像边缘添加1圈0（防止输出尺寸缩小太多）
#
# 输出结果：
# 检测到四个角的变化（正负值表示边缘方向）
# 中心区域值接近0（没有明显边缘）

import numpy as np


# 简单的 2D 卷积函数
def conv2d(inputs, kernel, stride=1, padding=0):
    """
    参数:
    inputs : 输入矩阵 (2D numpy数组)
    kernel : 卷积核 (2D numpy数组)
    stride : 滑动步长 (默认1)
    padding: 边缘填充0的圈数 (默认0)

    返回:
    output : 卷积结果
    """

    # 1. 添加边缘填充 (padding)
    if padding > 0:
        # 在上下左右各添加padding圈0
        padded_input = np.pad(inputs, pad_width=padding, mode='constant')
    else:
        padded_input = inputs

    # 2. 获取输入和卷积核的尺寸
    in_h, in_w = padded_input.shape
    k_h, k_w = kernel.shape

    # 3. 计算输出尺寸
    out_h = (in_h - k_h) // stride + 1
    out_w = (in_w - k_w) // stride + 1

    # 4. 初始化输出矩阵
    output = np.zeros((out_h, out_w))

    # 5. 执行卷积操作
    for h in range(0, out_h):  # 输出高度方向
        for w in range(0, out_w):  # 输出宽度方向
            # 计算当前窗口位置
            h_start = h * stride
            h_end = h_start + k_h
            w_start = w * stride
            w_end = w_start + k_w

            # 提取输入窗口
            window = padded_input[h_start:h_end, w_start:w_end]

            # 卷积计算：对应元素相乘后求和
            output[h, w] = np.sum(window * kernel)

    return output


# 测试示例
if __name__ == "__main__":
    # 创建一个简单的输入图像 (6x6)
    input_image = np.array([
        [1, 1, 1, 0, 0, 0],
        [1, 1, 1, 0, 0, 0],
        [1, 1, 1, 0, 0, 0],
        [0, 0, 0, 1, 1, 1],
        [0, 0, 0, 1, 1, 1],
        [0, 0, 0, 1, 1, 1]
    ])

    # 创建边缘检测卷积核 (3x3)
    edge_kernel = np.array([
        [-1, -1, -1],
        [-1, 8, -1],
        [-1, -1, -1]
    ])

    # 执行卷积操作
    output = conv2d(input_image, edge_kernel, stride=1, padding=1)

    # 打印结果
    print("输入图像:")
    print(input_image)
    print("\n卷积核 (边缘检测):")
    print(edge_kernel)
    print("\n卷积结果:")
    print(output)